<?php

namespace app\admin\controller;
use app\admin\core\Context;
use app\admin\core\Module;
use app\admin\model\Mp;
vendor('wechat/autoload');
use app\admin\model\MpReply;
use EasyWeChat\Foundation\Application;
use EasyWeChat\Message\Image;
use EasyWeChat\Message\News;
use think\Config;
use think\Controller;

class MpAccess extends Controller {
    const SESSION_PREFIX = 'weipeter_';
    const SESSION_KEY_INFO = 'oauth_user_info';
    const SESSION_KEY_TARGET_URL = 'oauth_target_url';
    /**
     * @var \EasyWeChat\Foundation\Application
     */
    public $app;

    private function initApp($mp) {
        if(!$mp) {
            $this->error('错误');
        }
        $options = array_merge(
            Config::get('mp_options'),
            [
                'app_id'=> $mp['appid'],
                'secret'=> $mp['appsecret'],
                'token' => $mp['token'],
            ]
        );
        $this->app = new Application($options);
    }
    public function index($interfaceToken) {
        $mp = Mp::get(['interface_token'=>$interfaceToken]);
        $this->initApp($mp);

        // 自动回复
        $this->app->server->setMessageHandler(function($message) use ($mp){
            // 执行消息监听器
            $context = new Context($message->FromUserName);
            $listeners = MpReply::all(['type'=>MpReply::TYPE_MESSAGE_LISTENER]);
            foreach ($listeners as $listener) {
                $context->setName($listener['content']);
                $obj = $this->newMpController($listener['content'],$context,$this->app,$mp);
                $result = $obj->messageListener($message);
                if($result!==false) {
                    return $result;
                }
            }

            // 处理消息上下文
            $context = new Context($message->FromUserName);
            if($context->inContext()) {
                // 有消息上下文
                $obj = $this->newMpController($context->getName(),$context,$this->app,$mp);
                return $obj->messageHandler($message);
            }


            // 处理消息
            if($message->MsgType == 'text') {
                $keyword = $message->Content;
                $moduleName = MpReply::getReplyModule($keyword);
                if($moduleName) {
                    // 看看哪个模块的关键字对应，则调用此模块的messageHandler方法
                    $context->setName($moduleName);
                    $obj = $this->newMpController($moduleName,$context,$this->app,$mp);

                    $result = $obj->messageHandler($message);
                }else {
                    // 如果没有模块处理，则使用系统自带的自动回复处理
                    $result = $this->messageHandler($keyword);
                }
                if($result!==false){
                    return $result;
                }
            }


            // 默认消息处理
            $handlers = MpReply::all(['type'=>MpReply::TYPE_DEFAULT_MESSAGE_HANDLER]);
            foreach ($handlers as $handler) {
                $context->setName($handler['content']);
                $obj = $this->newMpController($handler['content'],$context,$this->app,$mp);
                $result = $obj->defaultMessageHandler($message);
                if($result!==false) {
                    return $result;
                }
            }


            return null;
        });
        $this->app->server->serve()->send();
    }

    /**
     * 网页授权回调函数
     */
    public function oauthCallback() {
        $mp = get_bind_mp();
        $this->initApp($mp);
        $user = $this->app->oauth->user()->toArray();
        session(self::SESSION_KEY_INFO,$user,self::SESSION_PREFIX);
        $targetUrl = session(self::SESSION_KEY_TARGET_URL,'',self::SESSION_PREFIX);
        if(!$targetUrl) {
            $targetUrl = '/';
        }
        header('location:'. $targetUrl);
    }

    /**
     * 回复消息处理
     * @param $keyword
     * @return Image|News
     */
    private function messageHandler($keyword) {
        $reply = MpReply::get(['keyword'=>$keyword]);
        switch ($reply['type']) {
            case MpReply::TYPE_TEXT:
                return $reply['content'];
                break;
            case MpReply::TYPE_IMAGE:
                $imgPath = $this->urlToPath(get_img_path($reply['content']));
                $result = $this->app->material_temporary->uploadImage($imgPath);
                return new Image(['media_id'=>$result['media_id']]);
                break;
            case MpReply::TYPE_NEWS:
                $content = json_decode($reply['content'],true);
                $config = [];
                if($content['title'])
                    $config['title'] = $content['title'];
                if($content['desc'])
                    $config['description']=$content['desc'];
                if($content['cover'])
                    $config['image'] = 'http://' . $_SERVER['HTTP_HOST'] . get_img_path($content['cover']);
                if($content['url'])
                    $config['url'] = $content['url'];
                return new News($config);
                break;
        }
        return false;
    }
    private function urlToPath($imgPath) {
        $imgPath = ROOT_PATH.DS.'public'.DS.str_replace(ROOT_URL,'',$imgPath);
        return preg_replace("/[\\".DS."]+/",'/',$imgPath);
    }
    private function newMpController($moduleName,$context = null,$app = null,$mp = null){
        $class = "\\app\\{$moduleName}\\controller\\Mp";
        return new $class($context,$app,$mp);
    }
}